#ifndef __EKOS_KERNEL_PROC_H__
#define __EKOS_KERNEL_PROC_H__

#define PROC_KSTACK_TOP(_pid) (KSTACK + ((_pid + 1) << KSTACK_SHIFT))

extern volatile struct proc_t *procs;

struct env_t
{
	 union
	 {
		  struct
		  {
		  	   spin_lock_t lock;
			   int adm_level;
			   physaddr_t vpt;
		  	   int instance_count;
		  };

		  proc_id_t free_next;
	 };
};

extern volatile struct env_t envs[PROCESS_MAX_COUNT];

/* scheduler ================================================== */

/* hint -- called by time interrupt */
#define SCH_HINT_PERIOD 0
/* hint -- called by user that really want to be switched out */
#define SCH_HINT_FORCE  1

/* do schedule for current lcpu */
physaddr_t do_schedule(uint32_t *esp, uint32_t *eflags, int hint);
int sch_wait_pretend(int level);
int sch_wait_try();
int sch_wait(int level);
int sch_notify(proc_id_t pid, int level);
int sch_attach(proc_id_t pid);
int sch_detach(proc_id_t pid);


/* process management ========================================= */

/* set attributes of current process */
int proc_set_priority(int pid, int priority);
int proc_set_signal_handler(uintptr_t sh);
int proc_set_signal_flags(uint32_t flags);

proc_id_t env_alloc(physaddr_t vpt);
void env_free(proc_id_t env);

int proc_signal(proc_id_t proc, uint32_t sig);
/* The proc management */
int proc_fork(struct trapframe_t *tf, int proc);
int proc_kill(int proc);

int env_create(struct trapframe_t *tf, physaddr_t vpt,
			   uint32_t init_flags, uint32_t init_eflags, int init_priority,
			   int ex_ap);

void proc_wait_lock(proc_id_t proc);
void proc_wait_unlock(proc_id_t proc);

/* misc */

void send_exception(int pid, uint64_t info, int level);

#endif
